/*
 *  ConcreteNoteGeneratorTester.cpp
 *  SoundController0002
 *
 *  Created by jiro on 11/10/10.
 *  Copyright 2011 jiro music. All rights reserved.
 *
 */

#include "ConcreteNoteGeneratorTester.h"
#include "../../../sc/Tester/CustomAssert.h"
#include "../System0039.h"

namespace sc
{
namespace system0039
{
	 void ConcreteNoteGeneratorTester::TestAll()
	 {
		Test_GetConcreteNote000();
		Test_GetConcreteNote001();
		Test_GetConcreteNote002();
		Test_GetConcreteNote003();
	 }

	void ConcreteNoteGeneratorTester::Test_GetConcreteNote000()
	{
		double density = 1.0;
		double duration;
		::sc::hs::Sound::WaveType waveType = ::sc::hs::Sound::SingleSineWave;
		int noteCount = 10000;

		ConcreteNote note( waveType, Note::piano, Note::DSharp2, 1.0, Note::D1, 2.0 );
		duration = noteCount * note.GetDuration();
		ConcreteNoteGenerator generator( density, duration );
		generator.AddNote( note );

		AssertEqual( generator.GetNoteCount(), noteCount );
		for ( int i = 0; i < noteCount; i++ )
		{
			ConcreteNote noteGenerated = generator.GetConcreteNote();
			AssertTrue( noteGenerated == note );
		}
	}

	void ConcreteNoteGeneratorTester::Test_GetConcreteNote001()
	{
		double density = 0.5;
		double duration;
		::sc::hs::Sound::WaveType waveType = ::sc::hs::Sound::SingleSineWave;
		const int noteCount = 10000;
		int muteNoteCount = 0;

		ConcreteNote note( waveType, Note::piano, Note::DSharp2, 1.0, Note::D1, 2.0 );
		duration = noteCount * note.GetDuration();
		ConcreteNoteGenerator generator( density, duration );
		generator.AddNote( note );

		AssertEqual( generator.GetNoteCount(), noteCount );
		for ( int i = 0; i < noteCount; i++ )
		{
			ConcreteNote noteGenerated = generator.GetConcreteNote();
			if ( noteGenerated.GetDynamics() == 0 )
			{
				muteNoteCount++;
			}
			else
			{
				AssertTrue( noteGenerated == note );
			}
		}
		AssertLessOrEqual( 0.90 * ( noteCount / 2.0 ), muteNoteCount );
		AssertLessOrEqual( muteNoteCount, 1.10 * ( noteCount / 2.0 ) );
	}

	void ConcreteNoteGeneratorTester::Test_GetConcreteNote002()
	{
		double density = 1.0;
		double duration;
		::sc::hs::Sound::WaveType waveType = ::sc::hs::Sound::SingleSineWave;
		const int noteCount = 10000;
		int countOfDSharp2 = 0;

		ConcreteNote note0( waveType, Note::piano, Note::DSharp2, 1.0, Note::D1, 2.0 );
		ConcreteNote note1( waveType, Note::piano, Note::E2, 1.0, Note::D1, 2.0 );

		duration = noteCount * ( note0.GetDuration() + note1.GetDuration() ) / 2.0;
		ConcreteNoteGenerator generator( density, duration );
		generator.AddNote( note0 );
		generator.AddNote( note1 );

		AssertEqual( generator.GetNoteCount(), noteCount );
		for ( int i = 0; i < noteCount; i++ )
		{
			ConcreteNote noteGenerated = generator.GetConcreteNote();
			if ( noteGenerated == note0 )
			{
				countOfDSharp2++;
			}
			else if ( noteGenerated == note1 )
			{
			}
			else
			{
				AssertFail();
			}
		}
		AssertLessOrEqual( 0.90 * ( noteCount / 2.0 ), countOfDSharp2 );
		AssertLessOrEqual( countOfDSharp2, 1.10 * ( noteCount / 2.0 ) );
	}

	void ConcreteNoteGeneratorTester::Test_GetConcreteNote003()
	{
		double density = 0.50;
		double duration;
		::sc::hs::Sound::WaveType waveType = ::sc::hs::Sound::SingleSineWave;
		const int noteCount = 10000;
		int countOfDSharp2 = 0;
		int countOfMute = 0;

		ConcreteNote note0( waveType, Note::piano, Note::DSharp2, 1.0, Note::D1, 2.0 );
		ConcreteNote note1( waveType, Note::piano, Note::E2, 1.0, Note::D1, 2.0 );

		duration = noteCount * ( note0.GetDuration() + note1.GetDuration() ) / 2.0;
		ConcreteNoteGenerator generator( density, duration );
		generator.AddNote( note0 );
		generator.AddNote( note1 );

		AssertEqual( generator.GetNoteCount(), noteCount );
		for ( int i = 0; i < noteCount; i++ )
		{
			ConcreteNote noteGenerated = generator.GetConcreteNote();
			if ( noteGenerated == note0 )
			{
				countOfDSharp2++;
			}
			else if ( noteGenerated == note1 )
			{
//				cout << "E" << endl;
			}
			else if ( noteGenerated.GetDynamics() == 0.0 )
			{
				countOfMute++;
			}
			else
			{
				AssertFail();
			}
		}
		AssertLessOrEqual( 0.90 * ( noteCount / 4.0 ), countOfDSharp2 );
		AssertLessOrEqual( countOfDSharp2, 1.10 * ( noteCount / 4.0 ) );		
		AssertLessOrEqual( 0.90 * ( noteCount / 2.0 ), countOfMute );
		AssertLessOrEqual( countOfMute, 1.10 * ( noteCount / 2.0 ) );
	}

}
}
